package org.beetl.sql.core.db;

import org.beetl.sql.clazz.kit.BeetlSQLException;
import org.beetl.sql.clazz.kit.KeyWordHandler;
import org.beetl.sql.core.ConnectionSource;
import org.beetl.sql.core.ExecuteContext;
import org.beetl.sql.core.SQLExecutor;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.engine.template.SQLTemplateEngine;
import org.beetl.sql.core.meta.MetadataManager;
import org.beetl.sql.core.meta.SchemaMetadataManager;
import org.beetl.sql.core.range.RangeSql;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 用来描述数据库差异，主键生成，sql语句，翻页等，有一部分元数据的差异在{@link SchemaMetadataManager}
 *
 * @author xiandafu
 */
public interface DBStyle extends DBAutoGeneratedSql {

	/**
	 * 返回DBStyle名称
	 */
	String getName();

	/**
	 * 返回一个DBStyle代码
	 *
	 * @see DBType#DB_MYSQL
	 */
	int getDBType();

	/**
	 * 翻页语句实现
	 */
	RangeSql getRangeSql();

	/**
	 * 获取数据表id字段的类型：自增、序列、
	 *
	 * @see DBType#ID_AUTO
	 */
	int getIdType(Class c, String idProperty);

	KeyWordHandler getKeyWordHandler();

	/**
	 * 通过序列名字返回获取序列值的sql片段
	 *
	 * @param seqName 序列名称
	 * @return 返回使用序列的SQL语法
	 * @see org.beetl.sql.annotation.entity.SeqID
	 * @see OracleStyle#getSeqValue(String)
	 */
	String getSeqValue(String seqName);

	/**
	 * sql中的关键字处理
	 * @param keyWordHandler
	 */
	void setKeyWordHandler(KeyWordHandler keyWordHandler);

	//	  TODO,SQLExecutor里未实现

	/**
	 * jdbc 的 batch 个数在数据库收到限制，beetlsql会把批处理数据分批处理
	 * 这里配置了一个数据库允许的最大批处理个数，默认1000个
	 */
	default int getMaxBatchCount() {
		return 1000;
	}

	/**
	 * 是否是NoSql数据库
	 */
	default boolean isNoSql() {
		return false;
	}

	/**
	 * 对应的数据库是否支持jdbc metadata
	 */
	default boolean metadataSupport() {
		return true;
	}

	/**
	 * 是否支持PreparedStatement，对于数据库来说，几乎都支持，对于Nosql，则不一定支持
	 */
	default boolean preparedStatementSupport() {
		return true;
	}

	/**
	 * 批量插入或者更新的时候聚，数据库是否支持自动生成值，如自增
	 */
	default boolean batchGeneratedKeysSupport() {
		return true;
	}


	default void streamConfig(ResultSet resultSet) {
		try {
			resultSet.setFetchDirection(ResultSet.FETCH_FORWARD);
			resultSet.setFetchSize(100);
		} catch (SQLException exception) {
			throw new BeetlSQLException(BeetlSQLException.ERROR, exception);
		}
	}

	/**
	 * 如果不支持preparedStatement，在直接使用Statement的时候，返回输出变量到sql语句里，例如，当变量是字符串a"bc
	 * 应该输出{@code "a\"bc"}，注意，需要考虑SQL注入漏洞
	 *
	 * @param value 原值
	 * @return 转义后字符
	 */
	String wrapStatementValue(Object value);

	/**
	 * 得到一个SQL执行类{@code SQLExecutor},它是系统的核心类之一
	 */
	SQLExecutor buildExecutor(ExecuteContext executeContext);


	/**
	 * 初始化元数据管理器
	 * @param cs 数据链接源
	 */
	MetadataManager initMetadataManager(ConnectionSource cs);

	MetadataManager initMetadataManager(ConnectionSource cs, String defaultSchema, String defaultCatalog);

	/**
	 * 初始化DBStyle
	 * @param sqlTemplateEngine 执行SQL模板的引擎，默认beetl
	 * @param ps beetlsql配置信息
	 */
	void init(SQLTemplateEngine sqlTemplateEngine, Properties ps);

	/**
	 * 通过jdbc connection可以得到 schema和catalog，但可能低版本驱动不支持，这里提供数据库默认的
	 */
	String getDefaultSchema();

	/**
	 * 设置分页语句的起始偏移为0
	 */
	void setOffsetStartZero(boolean offsetStartZero);

	SQLTemplateEngine getSQLTemplateEngine();

	/**
	 * 在SQLManager配置好后，会调用此方法，最后对sqlmanager进行修改配置
	 *
	 * @see org.beetl.sql.core.nosql.ClickHouseStyle
	 */
	void config(SQLManager sqlManager);

}
